#include "stm32f10x.h"
#include "loopbuf.h"
#include "types.h"

#include <string.h>
#include <stdlib.h>

LOOPBUF *uart_tx_fifo = NULL;
LOOPBUF *uart_rx_fifo = NULL;


static UART_intconfig(USART_TypeDef *UARTx) {
	USART_ITConfig(UARTx, USART_IT_RXNE, ENABLE);
// 	USART_ITConfig(UARTx, USART_IT_TXE, ENABLE);
}

int STD_device_init(unsigned int baudrate) {
	USART_InitTypeDef USART_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	if (uart_tx_fifo) {
		lpbuf_destroy(uart_tx_fifo);
	}
	
	if (uart_rx_fifo) {
		lpbuf_destroy(uart_rx_fifo);
	}
	
	uart_tx_fifo = lpbuf_create(32);
	if (uart_tx_fifo == NULL)
		return -1;
	
	uart_rx_fifo = lpbuf_create(32);
	if (uart_rx_fifo == NULL) {
		lpbuf_destroy(uart_tx_fifo);
		return -1;
	}
	
	USART_InitStructure.USART_BaudRate = baudrate;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	
	/* Enable GPIO clock */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO, ENABLE);
	
	/* Remap the GPIO pins */
	GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);
	
	/* Configure USART Tx as alternate function push-pull */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);	

	/* Configure USART Rx as input floating */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	/* USART configuration */
	USART_Init(USART1, &USART_InitStructure);
	
	/* config USART interrupt */
	UART_intconfig(USART1);

	/* Enable USART */
	USART_Cmd(USART1, ENABLE);
	return 0;
}

int STD_device_deinit(void) {
	return 0;
}

int STD_getc(void) {
	unsigned char buffer;
	int count;
	
	do {
		USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
		count = lpbuf_read(uart_rx_fifo, &buffer, sizeof(buffer));
		USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	} while (count == 0);
	return buffer;
}

int STD_putc(char c) {
	USART_SendData(USART1, c);
    
	/* Loop until USARTy DR register is empty */ 
	while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
	return 0;
}


